/*
    文件内容: 封装TcpServer相关操作,封装创建Socket和EventLoop调用的地方,让main更加简洁
    文件名: TcpServer.h
    作者: 中国好青年(码农论坛)
    时间: 2024/9/8

*/
#pragma once
#include "EventLoop.h"
#include "Socket.h"
#include "InetAddress.h"
#include "Channel.h"
#include "Acceptor.h"
#include "ThreadPool.h"
#include <map>
#include <memory>
#include "util.h"
#include <mutex>

/*
    类名: EventLoop
    作用: 封装EventLoop相关操作类,封装主函数while循环和Epoll
*/
class TcpServer
{
private:
   int threadnums_;
   std::unique_ptr<EventLoop> mainloop_;
   std::vector<std::unique_ptr<EventLoop>> subloops_;
   Acceptor acceptserver_;
   ThreadPool threadpool_;
   std::mutex mutex_;
   std::map<int, spConnection> conns;
   std::function <void(spConnection)> newconnectioncallback_;
   std::function <void(spConnection)> closeconnectioncallback_;
   std::function <void(spConnection)> errorconnectioncallback_;
   std::function <void(spConnection, std::string&)> onmessagecallback_;
   std::function <void(spConnection)> sendcompletecallback_;
   std::function <void(EventLoop *)> epolltimeoutcallback_;

public:
    /* 构造函数 和 析构函数 */
    TcpServer(const std::string &ip, uint16_t port, int timeout, int threadnums = 3);
    ~TcpServer();

    /* EventLoop相关操作函数 */
    void start();
    void stop();

    void newConnection (std::unique_ptr<Socket> clientsock);
    void closeConnection (spConnection conn);
    void errorConnection (spConnection conn);
    void onmessage (spConnection conn, std::string &message);
    void sendComplete (spConnection conn);
    void epolltimeout (EventLoop *eploop);
    void removeConnfromMap(int fd);

    void setNewConnectionCallback  (std::function <void(spConnection)> newconnectioncallback);
    void setCloseConnectionCallback(std::function <void(spConnection)> closeconnectioncallback);
    void setErrorConnectionCallback(std::function <void(spConnection)> errorconnectioncallback);
    void setOnmessageCallback      (std::function <void(spConnection, std::string &)> onmessagecallback);
    void setSendCompleteCallback   (std::function <void(spConnection)> sendcompletecallback);
    void setsetEpollTimeoutCallback(std::function <void(EventLoop *)> epolltimeoutcallback);

};